.global _start_timer
.extern _timer_handler
;------------------------------------------------------------------------------
; Set up the timer's interrupt service routine.
; void start_timer()
_start_timer:
	; disable interrupts
	cli
	mov dx,#timer_stub ; address of stub routine
	push ds
	push si
	mov ax,#0 ; interrupts are at lowest memory
	mov ds,ax
	mov si,#0x20 ; timer interrupt vector (8 * 4)
	mov ax,cs 	; have interrupt go to the current (kernel) segment
	mov [si+2],ax
	mov [si],dx ; address of our vector
	pop si
	pop ds
	
	; port 0x43 is the command port; 0x36 = change frequency
	mov al,#0x36
	out #0x43,al
	
	; divisor = 1193180 / frequency
	; a frequency of 100 Hz means a divisor of 11932 (0x2E9C).
	; divisor has to be sent byte-wise, so split here into upper/lowerbytes.
	; lsb = divisor & 0xFF
	; msb = (divisor >> 8) & 0xFF
	; set a frequency of 100 Hz using a 0x2E9C as divisor (lsb = 9C; msb =2E).
	mov ax,#0x9C
	out #0x40,al
	mov ax,#0x2E
	out #0x40,al

	; enable interrupts
	sti
	ret
	;------------------------------------------------------------------------------
	; Interrupt service routine for hardware interrupt 8 (timer).
timer_stub:
	cli
	push ax
	push bx
	push cx
	push dx
	
	call _timer_handler
	
	pop dx
	pop cx
	pop bx
	
	; acknowledge the interrupt to the PIC. The code below resets
	; the PIC and disable the IF flags, although it shouldn't matter
	; as the flags will be restored by the iret instruction.
	
	mov al,#0x20
	out #0x20,al
	
	pop ax
	sti
	iret
